package com.fish;
/**
* @author Dror
*
* email: gumjum.o.o@gmail.com
*
*/
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collections;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.fileio.FileIO;
import com.graphics.Box;
import com.graphics.Camera;
import com.graphics.Shape;
import com.math.Quat;
import com.math.Vector;
public class World {
public static Aqu fishtank;
public static ArrayList<Shape> shapes;
public static ArrayList<Shape> sim_shapes;
public static ArrayList<Shape> distroy_shapes;
public static float money;
public static Camera cam;
static Shape shape,tmpshape;
static Fish tmpfish;
static Vector tmp = new Vector();
static Vector foo = new Vector();
static boolean debug = false;
static Fish selectedFish;
public static String sim_stat = "off";
public static boolean running = false;
public static String def = "test.xml";
public static int count = 0;
public static void initSim(){
shapes = new ArrayList<Shape> ();
sim_shapes = new ArrayList<Shape> ();
distroy_shapes = new ArrayList<Shape> ();
cam = new Camera(new Vector(0,0,-500),new Quat());
}
public static void show(Graphics g){
//Optimization:
// count += 1;
// count %= 10;
//
// if(count == 0)
Collections.sort(shapes);
for(Shape s: shapes){
s.xshow(g);
}
if(debug){
for(Shape s: sim_shapes){
if(s instanceof Fish)//to prevent double printing the fishfood
s.xshow(g);
}
}
}
/**
* start command for the simulation
*/
public static void startSimulation()
{
running = true;
sim_stat = "running";
}
/**
* resets command for the simulation
*/
public static void resetSimulation()
{
stopSimulation();
shapes.clear();
sim_shapes.clear();
sim_stat = "reseted";
fromXML(FileIO.readXMLFile(def));
}
public static void stopSimulation()
{
running = false;
sim_stat = "stopped";
}
/**
* Toggle debug mode on the fish
*/
public static void toggleDebug(){
debug = !debug;
}
/**
* Create new default fish of {@code type}
* @param type
* the fish type to be returned
* @return
* the new default fish
*/
public static Fish getDefFish(String type){
Element e = (Element)FileIO.defDB.getElementsByTagName("def").item(0);
e = (Element)e.getElementsByTagName(type).item(0).cloneNode(true);
e.setAttribute("type", type);
e.setAttribute("name", getRandomFishName());
e.setAttribute("generalInfo", getRandomFishBg());
e.setAttribute("value", getShopValue(type)+"");
return Fish.fromXML(e, cam);
}
/**
* add new default fish to the simulation.
* @param type
* the fish type to be added
*/
public static void addFish(String type) {
sim_shapes.add(getDefFish(type));
}
/**
* add new fishfood to the simulation
* @param food
* for future development - when fishfood types will be supported.
*/
public static void addFood(String food) {
Shape s = new FishFood(cam);
sim_shapes.add(s);
}
/**
* Check if there is a fish on the screen in the point (x,y) and
* returns it if so.
* @param x
* the x coordinate
* @param y
* the x coordinate
* @return
* the Fish that is in those coordinates
*/
public static Fish clicked(int x, int y) {
for(Shape s: sim_shapes){
if(s instanceof Fish){
tmpfish = (Fish)s;
if((x < Math.max(tmpfish.x[0], tmpfish.x[1]))&&(x > Math.min(tmpfish.x[0], tmpfish.x[1])))
if((y < Math.max(tmpfish.y[0], tmpfish.y[1]))&&(y > Math.min(tmpfish.y[0], tmpfish.y[1])))
return tmpfish;
}
}
return null;
}
/**
* moves the simulation forward
*/
public static void step(){
Shape s;
for(int i = 0;i<sim_shapes.size();i++){
s = sim_shapes.get(i);
if(s instanceof Fish)
((Fish)s).fishStep();
else if(s instanceof FishFood)
((FishFood)s).step();
}
cam.step();
}
/**
* return random name from the names file -> "data/names.txt".
* @return
* the random fish name
*/
private static String getRandomFishName(){
String r = FileIO.readTextFile("data/names.txt");
String [] l = r.split("\n");
return l[(int)(Math.random()*l.length)];
}
/**
* return random background from the background file -> "data/bg.txt".
* @return
* the random fish background
*/
private static String getRandomFishBg(){
String r = FileIO.readTextFile("data/bg.txt");
String [] l = r.split("\n");
return l[(int)(Math.random()*l.length)];
}
/**
* Get the shop value of an {@code item}.
* @param item
* the item to be checked
* @return
* the shop value of the item
*/
public static float getShopValue(String item){
NodeList l = ((Element)FileIO.shopDB.getElementsByTagName("shop").item(0)).getElementsByTagName("item");
for(int i = 0;i<l.getLength();i++){
Element e = (Element)l.item(i);
if(e.getAttribute("id").equals(item)){
return Float.parseFloat(e.getAttribute("value"));
}
}
return -1;
}
/**
* Converts the map to the xml format.
* @return
* the xml Document.
*/
public static Document toXML(){
Document doc = FileIO.newEmptyDoc();
Element map = doc.createElement("map");
map.setAttribute("money", ""+money);
for(Shape s:shapes){
map.appendChild(s.toXML(doc));
}
doc.appendChild(map);
return doc;
}
/**
* Load the simulation from and xml Document {@code doc}.
* @param doc
* the Document to load the simulation from.
*/
public static void fromXML(Document doc){
cam.reset();
shapes.clear();
Element map = (Element) doc.getElementsByTagName("map").item(0);
money = Float.parseFloat(map.getAttribute("money"));
NodeList nl = map.getElementsByTagName("Aqu");
Element e;
e = (Element)nl.item(0);
fishtank = Aqu.fromXML(e,cam);
shapes.add(fishtank);
for(int i = 1;i< nl.getLength();i++){
e = (Element)nl.item(i);
shapes.add(Box.fromXML(e,cam));
}
nl = map.getElementsByTagName("Fish");
for(int i = 0;i< nl.getLength();i++){
e = (Element)nl.item(i);
shapes.add(Fish.fromXML(e,cam));
}
}
/**
* Check if certain position if available for Fish {@code fi}.
* @param p
* the position to be checked
* @param fi
* the checked Fish
* @return
* if the position is available true, else false
*/
public static boolean checkFishPos(Vector p, Fish fi) {
if(fishtank.isInAqu(p)){
for(Shape s: sim_shapes){
if(s instanceof Fish && s != fi){
if(isNearFish((Fish)s,p))
return false;
}else if(s instanceof Box && s != fishtank){
if(isInBox((Box)s,p))
return false;
}
}
return true;
}
return false;
}
/**
* Check if certain position if available.
* @param p
* the position to be checked
* @return
* if the position is available true, else false
*/
public static boolean checkPos(Vector p) {
if(fishtank.isInAqu(p)){
for(Shape s: sim_shapes){
if(s instanceof Fish){
if(isNearFish((Fish)s,p))
return false;
}else if(s instanceof Box && s != fishtank){
if(isInBox((Box)s,p))
return false;
}
}
return true;
}
return false;
}
/**
* checks if a point {@code p} is near a fish {@code f}
*
* @param f
* is the fish
* @param p
* is the Vector of the point
* @return
* boolean value, true is the point is near the fish and false otherwise
*/
public static boolean isNearFish(Fish f, Vector p){
float curD = p.sub(f.p).length();
float minD = f.d.length()*1.2f;//1.2f is a safety distance.
if(curD < minD)
return true;
return false;
}
/**
* Checks if a certain point {@code p} is in box {@code b}.
* @param b
* the box
* @param p
* the certain point
* @return
* if the point is in the box true, else false.
*/
public static boolean isInBox(Box b,Vector p){
tmp.set(p);
tmp.reverseTransformation(b.r,b.p);
if(tmp.x < b.d.x && tmp.x > -b.d.x)
if(tmp.y < b.d.y && tmp.y > -b.d.y)
if(tmp.z < b.d.z && tmp.z > -b.d.z)
return true;
return false;
}
/**
* Get the first Fish from {@code type} to be found.
* @param type
* the fish type to search for
* @return
* the first fish to be found
*/
public static Fish getFirstOfType(String type) {
Fish f;
for(Shape s: sim_shapes){
if(s instanceof Fish){
f = (Fish)s;
if(f.type.equals(type))
return f;
}
}
return null;
}
/**
* get the closest fishfood to certain point {@code p}.
* @param p
* the certain point
* @return
* the closest fishfood
*/
public static FishFood getClosestFood(Vector p) {
FishFood f = null;
for(Shape s: sim_shapes){
if(s instanceof FishFood){
if(f==null)
f = (FishFood)s;
else if(Vector.distance(s.p, p) < Vector.distance(f.p, p))
f = (FishFood)s;
}
}
return f;
}
public static Fish getClosestFish(Vector p, String wantedFoodType) {
Fish f = null;
Fish t = null;
for(Shape s: sim_shapes){
if(s instanceof Fish){
t = (Fish)s;
if(t.type.equals(wantedFoodType)){
if(f==null)
f = t;
else if(Vector.distance(t.p, p) < Vector.distance(f.p, p))
f = t;
}
}
}
return f;
}
public static void toggleLines() {
Fish t;
for(Shape s: shapes){
if(s instanceof Fish){
t = (Fish)s;
t.toggle_lines();
}
}
}
public static Fish getClosestFishWithoutFish(Vector sp, String type,Fish fish) {
Fish f = null;
Fish t = null;
for(Shape s: sim_shapes){
if(s instanceof Fish){
t = (Fish)s;
if(t.type.equals(type) && !t.equals(fish)){
if(f==null)
f = t;
else if(Vector.distance(t.p, sp) < Vector.distance(f.p, sp))
f = t;
}
}
}
return f;
}
}